#include "write_lua.h"

#include "lang/lang.h"

#include "util/common_macros.h"
#include "util/mmgr.h"
#include "util/log.h"
#include "vfs/vfs.h"

#include <stdio.h>
#include <stdarg.h>
using namespace script; 


WriteLua::WriteLua() :
	m_TabC(0),
	m_pFile(0)
{

}
WriteLua::~WriteLua()
{
	UTIL_SAFE_DELETE(m_pFile);
}

void	WriteLua::OpenMemory()
{
	m_pFile = new util::MemoryFile();
	m_pFile->Open("memory", util::FileIO::FILE_ASCII | util::FileIO::FILE_WRITE);
}

bool	WriteLua::Open(const std::string& Name)
{
	if (m_pFile)
	{
		_LOG(MSG_WARNING, "WriteLua file already open: unable to open at " << Name);
		return false;
	}
	m_pFile = new util::FileIO();
	if (!m_pFile->Open(Name, util::FileIO::FILE_ASCII | util::FileIO::FILE_WRITE))
	{
		_LOG(MSG_WARNING, "Unable to open WriteLua file at " << Name);
		return false;
	}
	return true;
}

void	WriteLua::Write(const char*  _Msg, ...)
{
	if (!m_pFile || !m_pFile->IsOpen()) return;

	char Message[1024];
	va_list ArgP;
	va_start(ArgP, _Msg);
	vsprintf(Message, _Msg, ArgP);
	va_end(ArgP);

	m_pFile->WriteStr(Message);
}

void	WriteLua::WriteNL(const char*  _Msg, ...)
{
	if (!m_pFile || !m_pFile->IsOpen()) return;

	char Message[1024];
	va_list ArgP;
	va_start(ArgP, _Msg);
	vsprintf(Message, _Msg, ArgP);
	va_end(ArgP);

	m_pFile->WriteStr(GetTab());
	m_pFile->WriteStr( Message);
	m_pFile->WriteStr( "\n");
}

void	WriteLua::Indent()
{
	m_TabC ++;
}
void	WriteLua::Exdent()
{
	if (m_TabC > 0)
		m_TabC--;
}

std::string	WriteLua::GetTab()
{
	std::string	Tabs = "";
	for (int i=0; i<m_TabC; i++)
		Tabs += "   ";
	return Tabs;
}

void	WriteLua::StartTable(const std::string& Name)
{
	const std::string& Tab = GetTab();
	if (!Name.empty())
	{
		Write("%s%s = \n", Tab.c_str(), Name.c_str());
	} // otherwise it's an anonymous table
	Write("%s{ \n", Tab.c_str());
	Indent();
}
void	WriteLua::CloseTable(bool AddComma)
{
	Exdent();
	if (AddComma)
		Write("%s}, \n", GetTab().c_str());
	else
		Write("%s}\n\n", GetTab().c_str());
}

std::string	WriteLua::SanitizeString(const std::string& In)
{
	std::string	Out;
	for (unsigned int i=0; i<In.size(); i++)
	{
		if (In[i] == '"')
		{
			Out+="\\\"";
		} else
		if (In[i] == '\\')
		{
			Out+="/";
		} 
		else
		Out+=In[i];
	}
	return Out;
}

void	WriteLua::WritePair(const std::string& Name, const std::wstring& Data)
{
	Write("%s%s = \"%s\",\n", GetTab().c_str(), Name.c_str(), SanitizeString(lang::Lang::ConvertWtoA(Data)).c_str());
}

void	WriteLua::WritePair(const std::string& Name, const std::string& Data)
{
	Write("%s%s = \"%s\",\n", GetTab().c_str(), Name.c_str(), SanitizeString(Data).c_str());
}

/*void	WriteLua::WritePair(const std::string& Name, bool Data)
{
	Write("%s%s = %i,\n", GetTab().c_str(), Name.c_str(), Data ? 1 : 0);
}*/
void	WriteLua::WritePair(const std::string& Name, int Data)
{
	Write("%s%s = %i,\n", GetTab().c_str(), Name.c_str(), Data);
}
void	WriteLua::WritePair(const std::string& Name, float Data)
{
	Write("%s%s = %f,\n", GetTab().c_str(), Name.c_str(), Data);
}
void	WriteLua::WritePair(const std::string& Name, const math::Vec2& Data)
{
	Write("%s%s = { %f, %f },\n", GetTab().c_str(), Name.c_str(), Data.x, Data.y);

}
void	WriteLua::WritePair(const std::string& Name, const math::Vec3& Data)
{
	Write("%s%s = { %f, %f, %f },\n", GetTab().c_str(), Name.c_str(), Data.x, Data.y, Data.z);
}
void	WriteLua::WritePair(const std::string& Name, const math::Vec4& Data)
{
	Write("%s%s = { %f, %f, %f, %f },\n", GetTab().c_str(), Name.c_str(), Data.x, Data.y, Data.z, Data.w);
}
void	WriteLua::WritePair(const std::string& Name, const math::Spline2D& Data)
{
	Write("%s%s = { \n", GetTab().c_str(), Name.c_str());
		for (unsigned int i=0; i<Data.GetNodeC(); i++)
		{
			math::Vec2	Node = Data.GetNode(i)->Pos;
			Write("%s   { %f, %f }, \n", GetTab().c_str(), Node.x, Node.y);
		}
	Write("%s},\n", GetTab().c_str());
}